package com.infnoon.parking.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.infnoon.parking.common.ErrorCode;
import com.infnoon.parking.constant.CommonConstant;
import com.infnoon.parking.exception.BusinessException;
import com.infnoon.parking.model.dto.vehicles.RecordsQueryRequest;
import com.infnoon.parking.model.entity.Parkingrecords;
import com.infnoon.parking.service.ParkingbillService;
import com.infnoon.parking.service.ParkingrecordsService;
import com.infnoon.parking.mapper.ParkingrecordsMapper;
import com.infnoon.parking.service.VehiclesService;
import com.infnoon.parking.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

import static com.infnoon.parking.constant.FeeConstant.FEE_MS;

/**
* @author 31124
* @description 针对表【parkingrecords】的数据库操作Service实现
* @createDate 2024-12-16 14:54:54
*/
@Service
@Slf4j
public class ParkingrecordsServiceImpl extends ServiceImpl<ParkingrecordsMapper, Parkingrecords>
    implements ParkingrecordsService {
    // 因为需要 车进来的时候 把 车的相关信息 写进 Vehicles 数据库表中
    // 在这里引用 写进 Vehicles 数据库表 的 函数
    // 下面的 parkingbillService 同理， 在 车OUT 的时候 写进数据库
    @Resource
    private VehiclesService vehiclesService;

    @Resource
    private ParkingbillService parkingbillService;

    /**
     * 车入库
     * @param parkingRecordID 账单id
     * @param carnumber 车牌号
     * @return 一个值表示ok
     */
    @Override
    public long carRegister(Integer parkingRecordID, String carnumber) {
        // 1. 校验
        if (StringUtils.isAnyBlank(carnumber)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        synchronized (carnumber.intern()) {
            // 停车时 此车不能已经在 停车表 中
            QueryWrapper<Parkingrecords> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("carnumber", carnumber);
            queryWrapper.eq("isFinished", 0);
            long count = this.baseMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "此车已处停车状态");
            }
            // 2. 插入数据
            // 插入 Parking Records 停车记录 数据库表 的 数据
            // 通过 @Builder 注解 可以 链式赋值  省时便捷又安全
            Parkingrecords record = Parkingrecords.builder().
                    parkingRecordID(parkingRecordID).
                    carnumber(carnumber).
                    carLotNumber(0).
                    parkingFee(0.0F).
                    isFinished(1).
                    build();

            boolean saveResult = this.save(record);
            if (!saveResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "停车失败，数据库错误");
            }

            // 插入 Vehicles 车 数据库表 的 数据
            vehiclesService.saveVehicles(carnumber);
            return 1L;
        }
    }

    /**
     * 车 OUT
     * @param parkingRecordID 账单id
     * @param carnumber 车牌号
     * @return 此次停车的停车费
     */
    @Override
    public Float carOut(Integer parkingRecordID, String carnumber) {
        // 1. 校验
        if (StringUtils.isAnyBlank(carnumber)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        synchronized (carnumber.intern()) {
            // 车出库时 此车不能未在 停车表 中
            QueryWrapper<Parkingrecords> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("carnumber", carnumber);
            long count = this.baseMapper.selectCount(queryWrapper);
            if (count == 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "此车未处在停车状态");
            }

            // 2. 根据 订单号 获取 停车的时间
            Parkingrecords record = this.getBaseMapper().selectById(parkingRecordID);
            Date carCome = record.getTimeCome();

            // 3. 根据 时间的 diff 去收费
            // 获取当前的LocalDateTime
            LocalDateTime localDateTime = LocalDateTime.now();

            // 将LocalDateTime转换为Instant
            // 这里需要指定时区，否则会使用系统默认时区
            Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();

            // 将Instant转换为Date
            Date date = Date.from(instant);
            long diff = date.getTime() - carCome.getTime();
            Float fee = diff * FEE_MS;

            record.setTimeLeave(date);
            record.setParkingFee(fee);

            boolean saveResult = this.updateById(record);
            if (!saveResult) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "车出库失败，数据库错误");
            }

            // 插入 parkingbill 账单 数据库表 的 数据
            parkingbillService.saveParkingbill(parkingRecordID, date, fee);
            return fee;
        }
    }

    @Override
    public QueryWrapper<Parkingrecords> getQueryWrapper(RecordsQueryRequest recordsQueryRequest) {
        if (recordsQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        Integer parkingRecordID = recordsQueryRequest.getParkingRecordID();
        String carnumber = recordsQueryRequest.getCarnumber();

        int current = recordsQueryRequest.getCurrent();
        int pageSize = recordsQueryRequest.getPageSize();
        String sortField = recordsQueryRequest.getSortField();
        String sortOrder = recordsQueryRequest.getSortOrder();

        QueryWrapper<Parkingrecords> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(parkingRecordID != null, "parkingRecordID", parkingRecordID);
        queryWrapper.eq(StringUtils.isNotBlank(carnumber), "carnumber", carnumber);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }
}




